#ifndef __PROTOCOL_H__
#define __PROTOCOL_H__

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

#define DataSize_CommData_Uart 150

#define Prefix_Protocol_APA    0x7E
#define Postfix_Protocol_APA   0x7E
#define Transcode_Protocol_APA 0x5E

#define Count_ProtocolData_Max DataSize_CommData_Uart

#define ProtocolType_Protocol_APA  0x01
#define ProtocolType_Protocol_APB  0x02
#define ProtocolType_Protocol_APC  0x03
#define ProtocolType_Protocol_VPA  0x01
#define ProtocolType_Protocol_MCPA 0x01
#define ProtocolType_Protocol_MCPB 0x02

#define CmdID_Protocol_Alarm        0x01
#define CmdID_Protocol_Query        0x02
#define CmdID_Protocol_Set          0x03
#define CmdID_Protocol_Update       0x10
#define CmdID_Protocol_Version      0x11
#define CmdID_Protocol_UpdataReport 0xE0
#define CmdID_Protocol_RuQuery      0xF0
#define CmdID_Protocol_RuSet        0xD0

#define ReportKind_Alarm          0x01  // 告警
#define ReportKind_NewDevice      0x02  // 开站
#define ReportKind_Patrol         0x03  // 巡检
#define ReportKind_Repaire        0x04  // 故障修复
#define ReportKind_ConfigChange   0x05  // 配置变更
#define ReportKind_Login          0x06  // 系统登录
#define ReportKind_HeartBeat      0x07  // 心跳包
#define ReportKind_Update         0x08  // 软件更新
#define ReportKind_GPRSFail       0x09  // GPRS登录失败
#define ReportKind_SampleComplete 0x0A  // 批采结束
#define ReportKind_softExReset    0x11  // 软件异常复位
#define ReportKind_NewDevice_Ext  0xA0  // 远程模块开站使用的上报类型

#define CmdID_Protocol_Read  0x02
#define CmdID_Protocol_Write 0x03

#define VPFlag_Protocol_Normal     0x00
#define VPFlag_Protocol_Busy       0x01
#define VPFlag_Protocol_Initiative 0x80

#define Answer_Protocol_Success            0x00
#define Answer_Protocol_ConditionExecution 0x01
#define Answer_Protocol_CmdIDError         0x02
#define Answer_Protocol_LengthError        0x03
#define Answer_Protocol_CRCError           0x04
#define Answer_Protocol_OtherError         0xFE
#define Answer_Protocol_Initiative         0xFF

#define ParamFlag_Protocol_Normal      0x0000
#define ParamFlag_Protocol_Unknown     0x1000
#define ParamFlag_Protocol_OutRange    0x2000
#define ParamFlag_Protocol_Invalid     0x3000
#define ParamFlag_Protocol_LengthError 0x4000
#define ParamFlag_Protocol_TooLow      0x5000
#define ParamFlag_Protocol_TooHigh     0x6000
#define ParamFlag_Protocol_CannotCheck 0x7000
#define ParamFlag_Protocol_OtherError  0x9000

#define ReportMode_SMS      0x01
#define ReportMode_GPRS     0x02
#define ReportMode_DataCall 0x03

// 设备告警起始packet id
#define PacketID_Alarm_Min 0x8000
// 设备内部功能上报起始packet id
#define PacketID_Report_Min 0x8A00
// 本地监控功能上报起始packet id
#define PacketID_OMT_Report_Min 0x8F00
// 设备最大packet id
#define PacketID_Device_Max 0x8FFF

#define Length_Protocol_Checksum ((uint32_t)sizeof(((SProtocolData *)0)->checksum))
#define Length_Protocol_Head     ((uint32_t)((SProtocolData *)0)->datas)
#define Length_Protocol_Min      ((uint32_t)(Length_Protocol_Head + Length_Protocol_Checksum))  // 不包括包头包尾2个字节

#define Count_ParamItem_Max 50

typedef __packed struct __SProtocolData {
    uint8_t apType;
    uint8_t vpType;
    uint32_t majorNumber;
    uint8_t minorNumber;
    uint16_t packetID;
    uint8_t vpFlag;
    uint8_t mcpType;
    uint8_t cmdID;
    uint8_t answer;
    uint8_t datas[Count_ProtocolData_Max];
    uint16_t count;
    uint16_t checksum;
} SProtocolData;

typedef __packed struct _McpDataA {
    uint8_t length;
    uint16_t id;
    uint8_t datas[1];
} SMcpDataA;

typedef struct _ParamItem {
    uint8_t flag;
    uint16_t id;
    int8_t *value;
    uint8_t length;
} ParamItem;

typedef struct _ParamTable {
    ParamItem table[Count_ParamItem_Max];
    uint16_t tableIndex;
} ParamTable;

#define Registry_Param(a, b) registry_param(a, &b, sizeof(b));

#define ParamID_DnOutOverPowerAlarmOne 0x0332
#define ParamID_DnOutLackPowerAlarmOne 0x0333
#define ParamID_UpOutOverPowerAlarmOne 0x0334

#define ParamID_UpOutPowerOne 0x0514
#define ParamID_DnOutPowerOne 0x0511

#define ParamID_UpAttenuation_CH1 0x0442
#define ParamID_DnAttenuation_CH1 0x0443

#define ParamID_UpMaxGainOne 0x00B6
#define ParamID_DnMaxGainOne 0x00B7

#define ParamID_WorkFreqcommunicationMode_CW1 0x00B2

#define ParamID_CWNumber 0x0006

#define ParamID_UpRatedPowerOne 0x01F5
#define ParamID_DnRatedPowerOne 0x01F6

#define CommOrigin_OMT 0x02

void set_param_flag(void *value);
uint16_t getReportPacketID(void);
void registry_param(uint16_t id, void *value, uint8_t length);
uint32_t dataHandler(uint8_t commOrigin, uint8_t *buffer, uint32_t count, uint32_t size, uint32_t *end);
uint16_t cmdProtocol(uint8_t apType, uint8_t cmdID, uint16_t packetID, uint32_t majorNumber, uint8_t minorNumber, uint8_t mcpType, uint8_t *datas, uint32_t length, uint32_t size);
#endif  // __PROTOCOL_H__
